package com.tcm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tcm.common.enums.CachePrefix;
import com.tcm.entity.Role;
import com.tcm.entity.RoleUser;
import com.tcm.entity.Teacher;
import com.tcm.entity.User;
import com.tcm.entity.dto.TeacherUpdateDto;
import com.tcm.entity.vo.TeacherListResult;
import com.tcm.exception.DatabaseOperationException;
import com.tcm.exception.EntityAlreadyExistException;
import com.tcm.mapper.RoleMapper;
import com.tcm.mapper.RoleUserMapper;
import com.tcm.mapper.TeacherMapper;
import com.tcm.service.TeacherService;
import com.tcm.service.UserService;
import com.tcm.utils.AccessTokenUtil;
import com.tcm.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Guqier
 * @version 1.0
 * @date 2023/7/2 16:24
 */
@Slf4j
@Service
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements TeacherService {

    private static final String TEACHER_ROLE_KEY = "teacher";

    private static final Integer TEACHER_TYPE = 1;

    @Autowired
    private UserService userService;

    @Autowired
    private TeacherMapper teacherMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleUserMapper roleUserMapper;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 添加教师信息
     * @param teacherDto 教师信息Dto
     * @param accessToken accessToken
     * @return 添加结果，true为成功
     */
    @Override
    @Transactional// 开启事务
    public boolean addTeacherInfo(TeacherUpdateDto teacherDto, String accessToken){
        // 校验用户是否存在
        User user1 = userService.getUserByAccount(teacherDto.getAccount());
        if (user1 != null) {
            throw new EntityAlreadyExistException("账号已存在");
        }
        // 新建用户对象
        User user = userService.getNewFillInfoUser(teacherDto.getAccount(), teacherDto.getName(), teacherDto.getName(), TEACHER_TYPE,
                teacherDto.getGender(), teacherDto.getEmail(), teacherDto.getPhone(), AccessTokenUtil.getUserId(accessToken));
        // 保存用户信息
        boolean resU = userService.save(user);
        // 新建教师对象
        Teacher teacher = new Teacher();
        teacher.setAccount(teacherDto.getAccount());
        teacher.setName(teacherDto.getName());
        teacher.setPosition(TEACHER_TYPE);
        teacher.setCreateUser(AccessTokenUtil.getUserId(accessToken));
        teacher.setUpdateUser(AccessTokenUtil.getUserId(accessToken));
        // 保存教师对象
        boolean resT = this.save(teacher);
        // 保存角色关系
        LambdaQueryWrapper<Role> roleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleLambdaQueryWrapper.eq(Role::getRoleKey, TEACHER_ROLE_KEY);
        Role role = roleMapper.selectOne(roleLambdaQueryWrapper);
        RoleUser roleUser = new RoleUser();
        roleUser.setRoleId(role.getId());
        roleUser.setUserId(user.getId());
        roleUser.setCreateUser(AccessTokenUtil.getUserId(accessToken));
        roleUser.setUpdateUser(AccessTokenUtil.getUserId(accessToken));
        int insert = roleUserMapper.insert(roleUser);


        if (!resU || !resT || insert != 1){
            throw new RuntimeException("数据库执行错误");
        }
        return true;
    }

    /**
     * 获取所有教师信息
     * @return 教师信息列表
     */
    @Override
    public List<TeacherListResult> getTeacherList(){
        // 获取教师列表
        List<Teacher> teachers = teacherMapper.selectList(null);
        List<TeacherListResult> dto = new ArrayList<>();
        // 将Teacher对象转换为TeacherListResult
        return transferTeacherToListResult(teachers);
    }

    /**
     * 通过教师ID删除教师
     * @param userId 当前登录用户ID
     * @param teacherId 欲删除教师ID
     * @return 删除结果，true为成功
     */
    @Override
    @Transactional// 开启事务，当抛出RuntimeException时回滚事务
    public boolean removeTeacherById(Long userId, String teacherId) throws DatabaseOperationException{
        // 从查询教师表
        Teacher teacher = teacherMapper.selectById(teacherId);
        if (teacher == null) {
            return false;// 教师信息不存在
        }
        // 查询用户表
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getAccount, teacher.getAccount());
        User one = userService.getOne(queryWrapper);
        if (one == null) {
            return false;// 用户信息不存在
        }
        // 更新删除用户信息
        teacher.setUpdateUser(userId);
        teacherMapper.updateById(teacher);
        one.setUpdateUser(userId);
        userService.updateById(one);

        // 删除角色关系
        LambdaQueryWrapper<RoleUser> roleUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleUserLambdaQueryWrapper.eq(RoleUser::getUserId, one.getId());
        List<RoleUser> roleUsers = roleUserMapper.selectList(roleUserLambdaQueryWrapper);
        for (RoleUser roleUser : roleUsers) {
            roleUser.setUpdateUser(userId);
            roleUserMapper.updateById(roleUser);
            roleUserMapper.deleteById(roleUser.getId());
        }

        // 从数据表表删除
        int resT = teacherMapper.deleteById(teacherId);
        boolean resU = userService.removeById(one.getId());
        if(resT != 1 || !resU){
            throw new DatabaseOperationException("数据库删除失败");
        }
        redisUtil.deleteObject(CachePrefix.PC_USER_INFO.getCacheKey(one.getAccount()));
        return true;
    }

    /**
     * 批量删除教师信息
     * @param ids ID数组字符串
     * @param currUserId 当前登录用户ID
     * @return 删除结果，true为成功
     */
    @Override
    @Transactional
    public boolean removeTeacherBatchById(List<String> ids, Long currUserId){

        int cnt = 0;// 删除数量
        for (String id : ids) {
            boolean res = removeTeacherById(currUserId, id);
            if (res) {
                cnt++;
            }
        }
        if (cnt != ids.size()) {
            throw new DatabaseOperationException("数据库操作异常");
        }
        return true;
    }

    @Override
    @Transactional
    public boolean modifyTeacherInfo(TeacherUpdateDto teacherUpdateDto, Long currUserId) throws DatabaseOperationException{
        // 判断用户是否存在
        LambdaQueryWrapper<Teacher> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teacher::getAccount, teacherUpdateDto.getAccount());
        Teacher teacher = teacherMapper.selectOne(queryWrapper);
        if (teacher == null) {
            return false;
        }
        LambdaQueryWrapper<User> queryWrapperUser = new LambdaQueryWrapper<>();
        queryWrapperUser.eq(User::getAccount, teacherUpdateDto.getAccount());
        User user = userService.getUserByAccount(teacher.getAccount());

        if (user == null) {
            return false;// 教师信息不存在
        }

        // 更新教师信息
        teacher.setName(teacherUpdateDto.getName());
        teacher.setPosition(TEACHER_TYPE);
        teacher.setUpdateUser(currUserId);
        boolean res1 = this.updateById(teacher);
        // 更新用户信息
        user.setName(teacherUpdateDto.getName());
        user.setNickname(teacherUpdateDto.getName());
        user.setGender(teacherUpdateDto.getGender());
        user.setPhone(teacherUpdateDto.getPhone());
        user.setEmail(teacherUpdateDto.getEmail());
        user.setUpdateUser(currUserId);
        redisUtil.deleteObject(CachePrefix.PC_USER_INFO.getCacheKey(user.getAccount()));
        boolean res2 = userService.updateById(user);

        if (!res1 || !res2) {
            throw new DatabaseOperationException("数据库处理错误");
        }
        return true;
    }

    /**
     * 根据教师账号获取教师信息
     * @param account 教师账号
     * @return 教师信息实体类对象
     */
    @Override
    public Teacher getTeacherByAccount(String account){
        LambdaQueryWrapper<Teacher> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teacher::getAccount, account);
        return this.getOne(queryWrapper);
    }

    /**
     * 将教师实体类转换为展示类
     * @param teachers 教师实体类列表
     * @return 教师展示类
     */
    @Override
    public List<TeacherListResult> transferTeacherToListResult(List<Teacher> teachers){
        return teachers.stream().map(teacher -> {
            TeacherListResult teacherListResult = new TeacherListResult();
            BeanUtils.copyProperties(teacher, teacherListResult);

            // 查询其他信息
            User user = userService.getUserByAccount(teacher.getAccount());
            teacherListResult.setGender(user.getGender());
            teacherListResult.setPhone(user.getPhone());
            teacherListResult.setEmail(user.getEmail());
            return teacherListResult;
        }).collect(Collectors.toList());
    }
}
